<template>
  <Upload
    v-model:file-list="fileList"
    list-type="picture-card"
    :show-upload-list="true"
    :before-upload="beforeUpload"
    :custom-request="customRequest"
    @change="handleChange"
    @preview="handlePreview"
  >
    <div v-if="fileList.length < 4">
      <plus-outlined />
      <div style="margin-top: 8px">上传图片</div>
    </div>
  </Upload>
  <div style="display: none">
    <ImagePreviewGroup
      :preview="{
        visible,
        current,
        onVisibleChange: vis => visible = vis
      }"
    >
      <Image v-for="item in fileList" :key="item.uid" :src="item.response?.url">
      </Image>
    </ImagePreviewGroup>
  </div>
</template>
<script setup lang="tsx">
import { ref } from 'vue';
import { PlusOutlined } from '@ant-design/icons-vue';
import {
  Image,
  ImagePreviewGroup,
  Modal,
  Upload,
  UploadChangeParam,
  UploadFile,
  type UploadProps,
  message,
} from 'ant-design-vue';
import { AxiosRequestConfig } from 'axios';

const emits = defineEmits(['updateImgUrl']);

interface Props {
  uploadApi: (data: FormData, config: AxiosRequestConfig) => Promise<any>;
}

const props = defineProps<Props>();

const current = ref(0);
const visible = ref(false);
const imgModal = ref(false);
const titleModal = ref('');

const fileList = ref<UploadFile<{ url: string }>[]>([]);

const handleChange = (info: UploadChangeParam) => {
  if (!info.file.status) {
    const index = fileList.value?.findIndex(
      (item) => item.uid === info.file.uid,
    );
    fileList.value?.splice(index!, 1);
    return;
  }

  let urlList = fileList.value.map((res) => res.response?.url);

  emits('updateImgUrl', { imgUrl: urlList.join(',') });
};

function getBase64(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
}
const handlePreview = async (file: UploadProps['fileList'][number]) => {
  current.value = fileList.value?.findIndex(item=> item.name === file.name) || 0;
  
  if (!file.url && !file.preview) {
    file.preview = (await getBase64(file.originFileObj)) as string;
  }
  imgModal.value = true;
  titleModal.value =
    file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
  visible.value = true;
};

const handleCancel = () => {
  imgModal.value = false;
  titleModal.value = '';
};

const beforeUpload = (file: UploadProps['fileList'][number]) => {
  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  if (!isJpgOrPng) {
    message.error('请上传jpg/png图片!');
  }
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    message.error('图片最大支持2MB!');
  }
  return isJpgOrPng && isLt2M;
};

const customRequest: UploadProps['customRequest'] = ({
  file,
  filename,
  onError,
  onSuccess,
  onProgress,
}) => {
  const formData = new FormData();
  formData.append('file', file, file.name);
  formData.append('fileName', file.name);
  props
    .uploadApi(formData, {
      skipError: true,
      onUploadProgress: onProgress,
    })
    .then((success) => {
      onSuccess?.({ url: success.data.fileHttpUrl });
    })
    .catch((err) => {
      Modal.error({
        title: '提示',
        content: err.message,
        onOk() {
          fileList.value = fileList.value.filter(
            (item) => item.status != 'error',
          );
        },
      });
      onError?.(err);
    });
};
</script>
<style lang="scss" scoped>
:deep(.ant-upload-list-item) {
  padding: 0 !important;
}
:deep(.ant-upload-list-item::before) {
  width: 100% !important;
  height: 100% !important;
}
:deep(.ant-upload-list-item-actions) {
  display: flex;
  justify-content: center;
  align-items: center;
  .ant-btn-sm {
    height: 19px !important;
  }
}
</style>
